#pragma once
#include <algorithm>
#include <atomic>
#include <cstdarg>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <memory>
#include <mutex>
#include <random>
#include <set>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <vector>
#include <thread>

#ifndef _MSC_VER
#include <sys/time.h>
#endif

#ifdef _WIN32
#include <sys/timeb.h>
#include <sys/types.h>
#include <winsock2.h>

namespace burn {
inline int timeOfDay(struct timeval *t, void *timezone) {
  struct _timeb timebuffer;
  _ftime64_s(&timebuffer);
  t->tv_sec = timebuffer.time;
  t->tv_usec = 1000 * timebuffer.millitm;
  return 0;
};
} // namespace burn

#define __need_clock_t
#include <time.h>
/* Structure describing CPU time used by a process and its children.  */
namespace burn {
struct tms {
  clock_t tms_utime; /* User CPU time.  */
  clock_t tms_stime; /* System CPU time.  */

  clock_t tms_cutime; /* User CPU time of dead children.  */
  clock_t tms_cstime; /* System CPU time of dead children.  */
};

/* Store the CPU time used by this process and all its
   dead children (and their dead children) in BUFFER.
   Return the elapsed real time, or (clock_t) -1 for errors.
   All times are in CLK_TCKths of a second.  */
inline clock_t times(struct tms *__buffer) {
  __buffer->tms_utime = clock();
  __buffer->tms_stime = 0;
  __buffer->tms_cstime = 0;
  __buffer->tms_cutime = 0;
  return __buffer->tms_utime;
}

typedef long long suseconds_t;
} // namespace burn
#endif

#ifdef _MSC_VER
#undef min
#undef max
#endif

namespace burn {

template <bool B, typename T = void>
using c_enable_if_t = typename std::enable_if<B, T>::type;

template <typename T, typename... Args>
typename std::unique_ptr<T> c_make_unique(Args &&...args) {
  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

#if __cplusplus >= 201703L
using CGRAPH_READ_LOCK = std::shared_lock<std::shared_mutex>;
using CGRAPH_WRITE_LOCK = std::unique_lock<std::shared_mutex>;
#else
using CGRAPH_READ_LOCK =
    std::unique_lock<std::mutex>; // C++14不支持读写锁，使用mutex替代
using CGRAPH_WRITE_LOCK = std::unique_lock<std::mutex>;
#endif

#define CGRAPH_ASSERT_NOT_NULL_RETURN_NULL(ptr)                                \
  if (unlikely(nullptr == (ptr))) {                                            \
    return nullptr;                                                            \
  }

#define CGRAPH_ASSERT_NOT_NULL_THROW_ERROR(ptr)                                \
  if (unlikely(nullptr == (ptr))) {                                            \
    CGRAPH_THROW_EXCEPTION("input is null")                                    \
  }

#define CGRAPH_ASSERT_INIT_RETURN_NULL(isInit)                                 \
  if (unlikely((isInit) != is_init_)) {                                        \
    return nullptr;                                                            \
  }

#define CGRAPH_ASSERT_INIT(isInit)                                             \
  if (unlikely((isInit) != is_init_)) {                                        \
    return CStatus("init status is not suitable");                             \
  }

static std::mutex g_check_status_mtx;
#define CGRAPH_FUNCTION_CHECK_STATUS                                           \
  if (unlikely(status.isErr())) {                                              \
    std::lock_guard<std::mutex> lock{g_check_status_mtx};                      \
    CGRAPH_ECHO("%s | %s | line = [%d], errorCode = [%d], errorInfo = [%s].",  \
                __FILE__, __FUNCTION__, __LINE__, status.getCode(),            \
                status.getInfo().c_str());                                     \
    return status;                                                             \
  }

#define CGRAPH_CHECK_STATUS_RETURN_THIS_OR_NULL                                \
  return status.isOK() ? this : nullptr;

/* 删除资源信息 */
#define CGRAPH_DELETE_PTR(ptr)                                                 \
  if (unlikely((ptr) != nullptr)) {                                            \
    delete (ptr);                                                              \
    (ptr) = nullptr;                                                           \
  }

static const char *CGRAPH_EMPTY = "";
static const char *CGRAPH_BASIC_EXCEPTION = "burnpipe Exception";
static const char *CGRAPH_FUNCTION_NO_SUPPORT = "function no support";

static const int STATUS_OK = 0;   /** 正常流程返回值 */
static const int STATUS_ERR = -1; /** 异常流程返回值 */
static const char *STATUS_ERROR_INFO_CONNECTOR = " && ";

using CCHAR = char;
using CUINT = unsigned int;
using CVOID = void;
using CINT = int;
using CLONG = long;
using CULONG = unsigned long;
using CBOOL = bool;
using CBIGBOOL = int;
using CFLOAT = float;
using CDOUBLE = double;
using CCONSTR = const char *;
using CSIZE = size_t;
using CChar = CCHAR;
using CUint = CUINT;
using CSec = CUINT;  // 表示秒信息, for second
using CMSec = CUINT; // 表示毫秒信息, for millisecond
using CSize = CSIZE;
using CVoid = CVOID;
using CVoidPtr = CVOID *;
using CInt = CINT;
using CLevel = CINT;
using CLong = CLONG;
using CULong = CULONG;
using CBool = CBOOL;
using CIndex = CINT; // 表示标识信息，可以为负数
using CFloat = CFLOAT;
using CDouble = CDOUBLE;
using CConStr = CCONSTR; // 表示 const char*
using CBigBool = CBIGBOOL;

inline std::tm localtime_xp(std::time_t timer) {
  std::tm bt{};
#if defined(__unix__)
  localtime_r(&timer, &bt);
#elif defined(_MSC_VER)
  localtime_s(&bt, &timer);
#else
  static std::mutex mtx;
  std::lock_guard<std::mutex> lock(mtx);
  bt = *std::localtime(&timer);
#endif
  return bt;
}

static std::mutex g_echo_mtx;
inline CVoid CGRAPH_ECHO(const char *cmd, ...) {
#ifdef _CGRAPH_SILENCE_
  return;
#endif

  std::lock_guard<std::mutex> lock{g_echo_mtx};
  auto now = std::chrono::system_clock::now();
  // 通过不同精度获取相差的毫秒数
  uint64_t disMs =
      std::chrono::duration_cast<std::chrono::milliseconds>(
          now.time_since_epoch())
          .count() -
      std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch())
              .count() *
          1000;
  //   time_t tt = std::chrono::system_clock::to_time_t(now);
  std::time_t timestamp = std::time(nullptr);
  auto tm_time = localtime_xp(timestamp);
  char strTime[32] = {0};
  sprintf(strTime, "[%04d-%02d-%02d %02d:%02d:%02d.%03d]",
          tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday,
          tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, (int)disMs);
  std::cout << "[BURNPIPE] " << strTime << " ";

  va_list args;
  va_start(args, cmd);
  vprintf(cmd, args);
  va_end(args);
  std::cout << "\n";
}

auto constexpr BLOG = CGRAPH_ECHO;

#define BPTIMER_START(_X)                                                        \
  uint64_t _X##_start;                                                         \
  do {                                                                         \
    struct timeval current;                                                    \
    burn::timeOfDay(&current, NULL);                                        \
    _X##_start = current.tv_sec * 1000000 + current.tv_usec;                   \
  } while (0)

#define BPTIMER_STOP(_X)                                                         \
  uint64_t _X##_stop;                                                          \
  do {                                                                         \
    struct timeval current;                                                    \
    burn::timeOfDay(&current, nullptr);                                     \
    _X##_stop = current.tv_sec * 1000000 + current.tv_usec;                    \
  } while (0)

#define BPTIMER_USEC(_X) (float(_X##_stop - _X##_start))
#define BPTIMER_MSEC(_X) (float(_X##_stop - _X##_start) / 1000.0f)

class CSTATUS {
public:
  explicit CSTATUS() = default;

  explicit CSTATUS(const std::string &errorInfo) {
    this->error_code_ = STATUS_ERR; // 默认的error code信息
    this->error_info_ = errorInfo;
  }

  explicit CSTATUS(int errorCode, const std::string &errorInfo) {
    this->error_code_ = errorCode;
    this->error_info_ = errorInfo;
  }

  CSTATUS(const CSTATUS &status) {
    this->error_code_ = status.error_code_;
    this->error_info_ = status.error_info_;
  }

  CSTATUS(const CSTATUS &&status) noexcept {
    this->error_code_ = status.error_code_;
    this->error_info_ = status.error_info_;
  }

  CSTATUS &operator=(const CSTATUS &status) = default;

  CSTATUS &operator+=(const CSTATUS &cur) {
    if (this->isOK() && cur.isOK()) {
      return (*this);
    }

    error_info_ =
        this->isOK()
            ? cur.error_info_
            : (cur.isOK() ? error_info_
                          : (error_info_ + STATUS_ERROR_INFO_CONNECTOR +
                             cur.error_info_));
    error_code_ = STATUS_ERR;

    return (*this);
  }

  void setStatus(const std::string &info) {
    error_code_ = STATUS_ERR;
    error_info_ = info;
  }

  void setStatus(int code, const std::string &info) {
    error_code_ = code;
    error_info_ = info;
  }

  [[nodiscard]] int getCode() const { return this->error_code_; }

  [[nodiscard]] const std::string &getInfo() const { return this->error_info_; }
  void reset() {
    error_code_ = STATUS_OK;
    error_info_ = CGRAPH_EMPTY;
  }
  [[nodiscard]] bool isOK() const { return STATUS_OK == error_code_; }
  [[nodiscard]] bool isErr() const {
    return error_code_ < STATUS_OK; // 约定异常信息，均为负值
  }
  [[nodiscard]] bool isNotErr() const { return error_code_ >= STATUS_OK; }
  [[nodiscard]] bool isNotOK() const { return error_code_ != STATUS_OK; }

private:
  int error_code_{STATUS_OK}; // 错误码信息
  std::string error_info_;    // 错误信息描述
};

class CEXCEPTION : public std::exception {
public:
  explicit CEXCEPTION(const std::string &info = CGRAPH_EMPTY) {
    info_ = info.empty() ? CGRAPH_BASIC_EXCEPTION : info;
  }

  [[nodiscard]] const char *what() const noexcept override {
    return info_.c_str();
  }

private:
  std::string info_; // 异常状态信息
};

using CException = CEXCEPTION;
using CStatus = CSTATUS;
using CGRAPH_DEFAULT_FUNCTION = std::function<void()>;
using CGRAPH_DEFAULT_CONST_FUNCTION_REF = const std::function<void()> &;
using CGRAPH_CSTATUS_FUNCTION = std::function<CStatus()>;
using CGRAPH_CSTATUS_CONST_FUNCTION_REF = const std::function<CStatus()> &;
using CGRAPH_CALLBACK_FUNCTION = std::function<void(CStatus)>;
using CGRAPH_CALLBACK_CONST_FUNCTION_REF = const std::function<void(CStatus)> &;

enum class CFunctionType { INIT = 1, RUN = 2, DESTROY = 3 };
enum class G_EVENT_TYPE {
  SYNC = 0,  // 同步模式
  ASYNC = 1, // 异步模式
};
using GEventType = burn::G_EVENT_TYPE;

#define CGRAPH_FUNCTION_BEGIN CStatus status;
#define CGRAPH_FUNCTION_END return status;
#define CGRAPH_EMPTY_FUNCTION return CStatus();
#define CGRAPH_NO_SUPPORT return CStatus(CGRAPH_FUNCTION_NO_SUPPORT);
#define CGRAPH_RETURN_ERROR_STATUS(info) return CStatus(info);

#define CGRAPH_NO_ALLOWED_COPY(CType)                                          \
  CType(const CType &) = delete;                                               \
  const CType &operator=(const CType &) = delete;

#define CGRAPH_THROW_EXCEPTION(info) throw CException(info);

#define CGRAPH_SLEEP_SECOND(s)                                                 \
  std::this_thread::sleep_for(std::chrono::seconds(s));

static const CMSec CGRAPH_MAX_BLOCK_TTL = 10000000; // 最大阻塞时间，单位为ms

class USpinLock;

class CDescInfo {
public:
  const std::string &getName() const { return name_; }
  const std::string &getSession() const { return session_; }
  const std::string &getDescription() const { return description_; }

  virtual auto setName(const std::string &name) -> decltype(this) {
    name_ = name;
    return this;
  }

  virtual auto setDescription(const std::string &description)
      -> decltype(this) {
    description_ = description;
    return this;
  }

protected:
  std::string name_;        // 名字
  std::string session_;     // 唯一id信息
  std::string description_; // 描述信息
};

template <class T> class USerialUniqueArray {
public:
  CVoid uniqueAdd(const T &val) {
    // 如果没有，就插入array中
    if (inner_set_.find(val) == inner_set_.end()) {
      inner_set_.insert(val);
      inner_array_.push_back(val);
    }
  }

  CVoid getUniqueArray(std::vector<T> &arr) {
    for (const auto &iter : inner_array_) {
      arr.push_back(iter);
    }
  }

  CVoid clear() {
    inner_set_.clear();
    inner_array_.clear();
  }

private:
  std::set<T> inner_set_;      // 内部set，留比对使用
  std::vector<T> inner_array_; // 内部array，最终提供的排序不重复内容
};

class CObject {
public:
  explicit CObject() = default;
  virtual CStatus init() { CGRAPH_EMPTY_FUNCTION }
  virtual CStatus run() = 0;
  virtual CStatus destroy() { CGRAPH_EMPTY_FUNCTION }
  virtual ~CObject() = default;
};

static std::mutex g_session_mtx;
class UAllocator : public CObject {
public:
  template <typename T,
            c_enable_if_t<std::is_base_of<CObject, T>::value, int> = 0>
  static T *safeMallocCObject() {
    T *ptr = nullptr;
    while (!ptr) {
      ptr = new (std::nothrow) T();
    }
    return ptr;
  }

  template <typename T, typename... Args,
            c_enable_if_t<std::is_base_of<CObject, T>::value, int> = 0>
  static T *safeMallocTemplateCObject(Args... args) {
    T *ptr = nullptr;
    while (!ptr) {
      ptr = new T(std::forward<Args>(args)...);
    }
    return ptr;
  }

  template <typename T,
            c_enable_if_t<std::is_base_of<CObject, T>::value, int> = 0>
  static std::unique_ptr<T> makeUniqueCObject() {
    return c_make_unique<T>();
  }
};

#define CGRAPH_SAFE_MALLOC_COBJECT(Type) UAllocator::safeMallocCObject<Type>();
#define CGRAPH_MAKE_UNIQUE_COBJECT(Type) UAllocator::makeUniqueCObject<Type>();

using CGRAPH_RANDOM_MT19937 = std::mt19937;             // 梅森旋转法
using CGRAPH_RANDOM_MINSTD_RAND = std::minstd_rand;     // 线性同余法
using CGRAPH_RANDOM_RANLUX24_BASE = std::ranlux24_base; // 滞后Fibonacci

const static CInt CGRAPH_REAL_RANDOM = 0;

template <typename T = CFloat, CInt SEED = CGRAPH_REAL_RANDOM,
          typename TEngine = CGRAPH_RANDOM_MT19937>
class URandom {
public:
  static CStatus generate(std::vector<T> &data, CSize dim, const T &minValue,
                          const T &maxValue) {
    std::random_device rd;
    TEngine eng(CGRAPH_REAL_RANDOM == SEED ? rd() : SEED);
    std::uniform_real_distribution<T> urd(minValue, maxValue);

    data.clear();
    data.reserve(dim);
    for (CSize i = 0; i < dim; i++) {
      data.emplace_back(urd(eng));
    }

    return CStatus();
  }

  static CStatus generate(std::vector<std::vector<T>> &data, CSize height,
                          CSize column, const T &minValue, const T &maxValue) {
    std::random_device rd;
    TEngine eng(CGRAPH_REAL_RANDOM == SEED ? rd() : SEED);
    std::uniform_real_distribution<T> urd(minValue, maxValue);

    data.clear();
    data.reserve(height);
    std::vector<T> arr;
    arr.reserve(column);

    for (CSize i = 0; i < height; i++) {
      arr.clear();
      for (CSize j = 0; j < column; j++) {
        arr.emplace_back(urd(eng));
      }
      data.emplace_back(arr);
    }

    return CStatus();
  }

  static std::string generateSession(const std::string &key = "object",
                                     CSize size = 3) {
    std::string session; // 形式是 a-b-c-key，其中 a表示6位随机数字
    std::vector<CFloat> vec;
    URandom<CFloat>::generate(vec, size, 100000, 999999);
    for (CSize i = 0; i < size; i++) {
      session += std::to_string(int(vec[i]));
      session += '-';
    }
    session += key;
    return session;
  }
};

class GraphObject : public CObject {
public:
  CStatus run() override = 0;

protected:
  CBool is_init_ = false; // 判断是否init
};

class GElementObject : public GraphObject {};

class GParamObject : public GraphObject {
protected:
  CStatus run() final { CGRAPH_NO_SUPPORT }
};

class UThreadPool;
class UThreadPoolPtr;
class GEventManager;

static const char *CGRAPH_STR_PIPELINE = "pipeline";
static const char *CGRAPH_STR_NODE = "node";
static const char *CGRAPH_STR_CLUSTER = "cluster";
static const char *CGRAPH_STR_REGION = "region";
static const char *CGRAPH_STR_CONDITION = "condition";
static const char *CGRAPH_STR_FUNCTION = "function";
static const char *CGRAPH_STR_SINGLETON = "singleton";

template <typename T,
          std::enable_if_t<std::is_base_of<GraphObject, T>::value, int> = 0>
class GraphManager : public CObject {
protected:
  virtual CStatus add(T *object) { CGRAPH_NO_SUPPORT }
  virtual CStatus remove(T *object) { CGRAPH_NO_SUPPORT }

  virtual CBool find(T *object) const { return false; }
  virtual CStatus create(const std::string &key) { CGRAPH_NO_SUPPORT }

  virtual T *get(const std::string &key) { return nullptr; }

  virtual CStatus reset() { CGRAPH_NO_SUPPORT }

  [[nodiscard]] virtual CSize getSize() const { return 0; }

  virtual CStatus clear() = 0;
  CStatus run() override { CGRAPH_NO_SUPPORT }
};

class GPassedParam : public GParamObject {
public:
  virtual CVoid clone(GPassedParam *param) = 0;
};

class GParam : public GParamObject {
public:
#if __cplusplus >= 201703L
  std::shared_mutex _param_shared_lock_; // 用于参数互斥的锁信息
#else
  std::mutex _param_shared_lock_;
#endif

  CStatus getBacktrace(std::vector<std::string> &trace);
  CVoid addBacktrace(const std::string &trace);
  CVoid cleanBacktrace();
  const std::string &getKey() const;

protected:
  virtual CStatus setup();
  virtual CVoid reset(const CStatus &curStatus) = 0;

private:
  std::string key_; // 对应的key信息
  USerialUniqueArray<std::string>
      backtrace_; // 记录参数的调用栈信息，仅记录get 此参数的地方。不包括
                  // create和remove的地方。
  CBool backtrace_enable_ = false; // 是否使能backtrace功能
  USpinLock *backtrace_lock_;      // 针对backtrace的自旋锁
  friend class GParamManager;
};

using GParamPtr = GParam *;

class GParamManager : public GParamObject, public GraphManager<GParam> {
public:
  template <typename T,
            c_enable_if_t<std::is_base_of<GParam, T>::value, int> = 0>
  CStatus create(const std::string &key, CBool backtrace = false);

  template <typename T,
            c_enable_if_t<std::is_base_of<GParam, T>::value, int> = 0>
  T *get(const std::string &key);

  CStatus remove(const std::string &key);
  CStatus getKeys(std::vector<std::string> &keys);

protected:
  explicit GParamManager();
  ~GParamManager() override;
  CStatus init() override;
  CStatus destroy() override;
  CStatus clear() final;
  CStatus setup();
  CVoid resetWithStatus(const CStatus &curStatus);

  CGRAPH_NO_ALLOWED_COPY(GParamManager)

private:
  std::unordered_map<std::string, GParam *>
      params_map_;   // 记录param信息的hash表
  std::mutex mutex_; // 创建param的时候上锁

  friend class GPipeline;
  friend class UAllocator;
};

using GParamManagerPtr = GParamManager *;

template <typename T, c_enable_if_t<std::is_base_of<GParam, T>::value, int>>
CStatus GParamManager::create(const std::string &key, CBool backtrace) {
  CGRAPH_FUNCTION_BEGIN
  std::lock_guard<std::mutex> lock(this->mutex_);
  auto result = params_map_.find(key);
  if (result != params_map_.end()) {
    /* 如果是重复创建，则返回ok；非重复创建（类型不同）则返回err */
    auto param = result->second;
    return (typeid(*param).name() == typeid(T).name())
               ? CStatus()
               : CStatus("create param duplicate");
  }

  T *ptr = CGRAPH_SAFE_MALLOC_COBJECT(T)((GParamPtr)ptr)->backtrace_enable_ =
      backtrace;
  ((GParamPtr)ptr)->key_ = key;
  params_map_.insert(std::pair<std::string, T *>(key, ptr));
  CGRAPH_FUNCTION_END
}

template <typename T, c_enable_if_t<std::is_base_of<GParam, T>::value, int>>
T *GParamManager::get(const std::string &key) {
  auto result = params_map_.find(key);
  if (result == params_map_.end()) {
    return nullptr;
  }
  return dynamic_cast<T *>(result->second);
}

// ------------- Param utils
#define CGRAPH_CREATE_GPARAM(Type, key) this->createGParam<Type>(key);
#define CGRAPH_GET_GPARAM(Type, key) this->getGParam<Type>(key);
#define CGRAPH_GET_GPARAM_WITH_NO_EMPTY(Type, key)                             \
  this->getGParamWithNoEmpty<Type>(key);
#define CGRAPH_GET_GPARAM_KEYS(keys) this->getGParamKeys(keys);
#define CGRAPH_DELETE_GPARAM(key) this->removeGParam(key);
#define CGRAPH_GET_EPARAM(Type, key) this->getEParam<Type>(key);
#define CGRAPH_PARAM_WRITE_CODE_BLOCK(param)                                   \
  burn::CGRAPH_WRITE_LOCK __paramWLock__((param)->_param_shared_lock_);
#define CGRAPH_PARAM_READ_CODE_BLOCK(param)                                    \
  burn::CGRAPH_READ_LOCK __paramRLock__((param)->_param_shared_lock_);

using GParamPtr = GParam *;
using GAspectParam = GPassedParam;
using GDaemonParam = GPassedParam;
using GElementParam = GPassedParam;
using GEventParam = GPassedParam;
using GPassedParamPtr = GPassedParam *;
using GAspectParamPtr = GAspectParam *;
using GDaemonParamPtr = GDaemonParam *;
using GElementParamPtr = GElementParam *;
using GEventParamPtr = GEventParam *;
using GElementParamMap = std::unordered_map<std::string, GElementParamPtr>;
using GEventManagerPtr = GEventManager *;

enum class GElementType {
  ELEMENT = 0x00000000,   // 元素
  NODE = 0x00010000,      // 节点
  GROUP = 0x00020000,     // 组
  CLUSTER = 0x00020001,   // 簇
  REGION = 0x00020002,    // 区域
  CONDITION = 0x00020004, // 条件
  ADAPTER = 0x00040000,   // 适配器
  FUNCTION = 0x00040001,  // 函数
  SINGLETON = 0x00040002, // 单例
};

enum class GEngineType {
  STATIC = 1, /** 静态图运行 */
  DYNAMIC = 2 /** 动态图运行 */
};

#define CGRAPH_ASSERT_NOT_NULL(ptr)                                            \
  if (unlikely(nullptr == (ptr))) {                                            \
    return CStatus("input is nullptr");                                        \
  }

#ifdef _ENABLE_LIKELY_
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#else
#define likely
#define unlikely
#endif

#define CGRAPH_DECLARE_GPARAM_MANAGER_WRAPPER                                  \
  template <typename TGParam,                                                  \
            c_enable_if_t<std::is_base_of<GParam, TGParam>::value, int> = 0>   \
  CStatus createGParam(const std::string &key, CBool backtrace = false) {      \
    CGRAPH_ASSERT_NOT_NULL(param_manager_)                                     \
    return param_manager_->create<TGParam>(key, backtrace);                    \
  }                                                                            \
  template <typename TGParam,                                                  \
            c_enable_if_t<std::is_base_of<GParam, TGParam>::value, int> = 0>   \
  TGParam *getGParam(const std::string &key) {                                 \
    CGRAPH_ASSERT_NOT_NULL_RETURN_NULL(param_manager_)                         \
    auto param = param_manager_->get<TGParam>(key);                            \
    if (nullptr != param) {                                                    \
      param->addBacktrace(name_.empty() ? session_ : name_);                   \
    }                                                                          \
    return param;                                                              \
  }                                                                            \
  template <typename TGParam,                                                  \
            c_enable_if_t<std::is_base_of<GParam, TGParam>::value, int> = 0>   \
  TGParam *getGParamWithNoEmpty(const std::string &key) {                      \
    auto *param = getGParam<TGParam>(key);                                     \
    if (nullptr == param) {                                                    \
      CGRAPH_THROW_EXCEPTION("param [" + key + "] is null")                    \
    }                                                                          \
    return param;                                                              \
  }                                                                            \
  CStatus removeGParam(const std::string &key) {                               \
    CGRAPH_ASSERT_NOT_NULL(param_manager_)                                     \
    return param_manager_->remove(key);                                        \
  }                                                                            \
  void *setGParamManager(GParamManagerPtr pm) {                                \
    this->param_manager_ = pm;                                                 \
    return this;                                                               \
  }                                                                            \
  CStatus getGParamKeys(std::vector<std::string> &keys) {                      \
    CGRAPH_ASSERT_NOT_NULL(param_manager_)                                     \
    return param_manager_->getKeys(keys);                                      \
  }

const static CMSec CGRAPH_DEFAULT_ELEMENT_RUN_TTL = 0;
const static CSize CGRAPH_DEFAULT_LOOP_TIMES = 1;
const static CLevel CGRAPH_DEFAULT_ELEMENT_LEVEL = 0;

class GElement : public GElementObject, public CDescInfo {
public:
  // const std::string &getName() const;
  // const std::string &getSession() const;

  // /**
  //  * 实现添加切面的逻辑
  //  * @tparam TAspect
  //  * @tparam TParam
  //  * @param param
  //  * @return
  //  */
  // template <
  //     typename TAspect, typename TParam = GAspectDefaultParam,
  //     std::enable_if_t<std::is_base_of<GAspect, TAspect>::value, int> = 0,
  //     c_enable_if_t<std::is_base_of<GAspectParam, TParam>::value, int> = 0>
  // GElement *addGAspect(TParam *param = nullptr);

  // /**
  //  * 实现添加模板切面的逻辑
  //  * @tparam TAspect
  //  * @tparam Args
  //  * @return
  //  */
  // template <
  //     typename TAspect, typename... Args,
  //     c_enable_if_t<std::is_base_of<GTemplateAspect<Args...>,
  //     TAspect>::value,
  //                   int> = 0>
  // GElement *addGAspect(Args... args);

  template <typename T,
            c_enable_if_t<std::is_base_of<GElementParam, T>::value, int> = 0>
  GElement *addEParam(const std::string &key, T *param);

  CStatus addDependGElements(const std::set<GElement *> &elements);
  GElement *setName(const std::string &name) override;
  GElement *setLoop(CSize loop);
  GElement *setLevel(CLevel level);

  CStatus notify(const std::string &key, GEventType type);
  GElement *setThreadPool(UThreadPoolPtr ptr);
  virtual CVoid dump(std::ostream &oss);

protected:
  explicit GElement();

  ~GElement() override;
  virtual CStatus beforeRun();
  virtual CStatus afterRun();
  virtual CBool isHold();

  virtual CStatus crashed(const CException &ex);

  [[nodiscard]] CBool isRunnable() const;

  [[nodiscard]] CBool isLinkable() const;

  virtual CStatus process(bool isMock);

  // /**
  //  * 执行切面逻辑
  //  * @param aspectType
  //  * @param curStatus
  //  * @return
  //  */
  // CStatus doAspect(const GAspectType &aspectType,
  //                  const CStatus &curStatus = CStatus());

  virtual CStatus setElementInfo(const std::set<GElement *> &dependElements,
                                 const std::string &name, CSize loop,
                                 GParamManagerPtr paramManager,
                                 GEventManagerPtr eventManager);

  template <typename T,
            c_enable_if_t<std::is_base_of<GElementParam, T>::value, int> = 0>
  T *getEParam(const std::string &key);

  CStatus fatProcessor(const CFunctionType &type);

  CIndex getThreadNum();

  CStatus notify(const std::string &key, CSize times = 1);
  GElement *setThreadPool(UThreadPool *ptr);
  CVoid dumpEdge(std::ostream &oss, GElement *src, GElement *dst,
                 const std::string &label = "");
  CVoid dumpElement(std::ostream &oss);

  CBool isGroup();

  CGRAPH_NO_ALLOWED_COPY(GElement);

  CGRAPH_DECLARE_GPARAM_MANAGER_WRAPPER

protected:
  CBool done_{false};     // 判定被执行结束
  CBool linkable_{false}; // 判定是否可以连通计算
  CSize loop_{1};         // 节点执行次数
  CLevel level_{0}; // 用于设定init的执行顺序(值小的，优先init，可以为负数)
  std::set<GElement *> run_before_; // 被依赖的节点
  std::set<GElement *> dependence_; // 依赖的节点信息
  std::atomic<CSize> left_depend_{
      0}; // 当 left_depend_ 值为0的时候，即可以执行该node信息
  GParamManagerPtr param_manager_{
      nullptr}; // 整体流程的参数管理类，所有pipeline中的所有节点共享
  // GAspectManagerPtr aspect_manager_{nullptr}; // 整体流程的切面管理类
  GEventManager *event_manager_;  // 事件管理类
  UThreadPool *thread_pool_;      // 用于执行的线程池信息
  GElementParamMap local_params_; // 用于记录当前element的内部参数
  GElementType element_type_;     // 用于区分element 内部类型

  friend class GNode;
  friend class GCluster;
  friend class GRegion;
  friend class GCondition;
  friend class GElementManager;
  friend class GGroup;
  friend class GPipeline;
  friend class GElementSorter;
  friend class GStaticEngine;
  friend class GDynamicEngine;
  template <typename T> friend class GSingleton;
};

class UTaskGroup;
class GNodeInfo;
class GFunction;
class GElementManager;
class GEvent;
class GEventDefaultParam;
// class GTemplateNode;
struct UThreadPoolConfig;

// using GTemplateNodePtr = GTemplateNode *;
using GElementPtr = GElement *;
using GFunctionPtr = GFunction *;
using GElementPtrArr = std::vector<GElementPtr>;
using GElementPtrSet = std::set<GElementPtr>;
using GElementPtrSetRef = GElementPtrSet &;
using GEventPtr = GEvent *;

class GGroup : public GElement {
public:
  explicit GGroup();

  virtual CStatus addElement(GElementPtr element) = 0;

  CStatus init() override;
  CStatus destroy() override;

protected:
  CVoid dumpGroupLabelBegin(std::ostream &oss);
  CVoid dumpGroupLabelEnd(std::ostream &oss);

protected:
  GElementPtrArr group_elements_arr_; // 存放 element的数组
};

using GGroupPtr = GGroup *;

class GEventObject : public GraphObject, public CDescInfo {
protected:
  explicit GEventObject() { session_ = URandom<>::generateSession("event"); }

  ~GEventObject() override{CGRAPH_DELETE_PTR(param_)}

  CStatus run() override {
    CGRAPH_NO_SUPPORT
  }

  virtual GEventObject *setThreadPool(UThreadPool *ptr) {
    thread_pool_ = ptr;
    return this;
  }

protected:
  UThreadPool *thread_pool_ = nullptr;       // 线程池类
  GParamManagerPtr param_manager_ = nullptr; // GParam参数管理类
  GEventParamPtr param_ = nullptr;           // 事件参数信息
};

class GEvent : public GEventObject {
protected:
  /**
   * 事件被触发的时候，执行的函数
   * @param param 是pipeline那一层，注册进来的参数，可以为空
   * @return
   */
  virtual CVoid trigger(GEventParamPtr param) = 0;

  CStatus run() final;
  CStatus process(GEventType type);

  CGRAPH_DECLARE_GPARAM_MANAGER_WRAPPER

  friend class GEventManager;
};

using GEventPtr = GEvent *;

class GEventManager : public GEventObject, public GraphManager<GEvent> {
public:
  /**
   * 创建一个特定类型的事件，并且通过参数赋值
   * @tparam TEvent
   * @tparam TEParam
   * @param key
   * @param param
   * @return
   */
  template <
      typename TEvent, typename TEParam = GEventDefaultParam,
      c_enable_if_t<std::is_base_of<GEvent, TEvent>::value, int> = 0,
      c_enable_if_t<std::is_base_of<GEventParam, TEParam>::value, int> = 0>
  CStatus createWithParam(const std::string &key, TEParam *param = nullptr);

  /**
   * 触发事件
   * @param key
   * @return
   */
  CStatus trigger(const std::string &key, GEventType type);

  CStatus init() override;

  CStatus destroy() override;

  //   CStatus clear() final;
  CStatus clear() override;

  GEventObject *setThreadPool(UThreadPool *ptr) override;

  explicit GEventManager() = default;

  ~GEventManager() override;

protected:
  CGRAPH_NO_ALLOWED_COPY(GEventManager)

private:
  std::unordered_map<std::string, GEventPtr> events_map_; // event 管理类

  friend class UAllocator;
  friend class GPipeline;
};

using GEventManagerPtr = GEventManager *;

enum class GNodeType { BASIC = 0, IO = 1, CPU = 2, GPU = 3 };

class GNode : public GElement {
protected:
  explicit GNode();
  CStatus doParallel(const UTaskGroup &tasks, CMSec ttl = CGRAPH_MAX_BLOCK_TTL);
  GNode *setType(const GNodeType &type);

private:
  GNodeType node_type_; // 节点类型
};
using GNodePtr = GNode *;
using GNodePtrArr = std::vector<GNodePtr>;

struct GNodeInfo : public GraphObject {
  std::string name_;                      // 名称
  CSize loop_{CGRAPH_DEFAULT_LOOP_TIMES}; // 循环次数
  GElementPtrSet dependence_;             // 依赖节点

  // 无依赖版本，适用于cluster创建
  explicit GNodeInfo(const std::string &name = CGRAPH_EMPTY,
                     CSize loop = CGRAPH_DEFAULT_LOOP_TIMES) {
    this->name_ = name;
    this->loop_ = loop;
  }

  // 有依赖版本，适用于region创建
  explicit GNodeInfo(
      const GElementPtrSet &dependence = std::initializer_list<GElementPtr>(),
      const std::string &name = CGRAPH_EMPTY,
      CSize loop = CGRAPH_DEFAULT_LOOP_TIMES) {
    this->name_ = name;
    this->loop_ = loop;
    this->dependence_ = dependence;
  }

private:
  CStatus run() override { CGRAPH_NO_SUPPORT }
};

template <typename... Args> class GTemplateNode : public GNode {};
template <typename... Args> using GTemplateNodePtr = GTemplateNode<Args...> *;

// ---------------- Main pipe API
class GPipelineObject : public GraphObject {};

class GPipeline : public GPipelineObject, public CDescInfo {
public:
  CStatus init() override;
  CStatus run() override;
  CStatus destroy() override;
  CStatus process(CSize runTimes = CGRAPH_DEFAULT_LOOP_TIMES);
  CStatus dump(std::ostream &oss = std::cout);

  template <typename T,
            c_enable_if_t<std::is_base_of<GNode, T>::value, int> = 0>
  GNodePtr createGNode(const GNodeInfo &info);

  template <typename T,
            c_enable_if_t<std::is_base_of<GGroup, T>::value, int> = 0>
  GGroupPtr createGGroup(const GElementPtrArr &elements,
                         const GElementPtrSet &dependElements =
                             std::initializer_list<GElementPtr>(),
                         const std::string &name = CGRAPH_EMPTY,
                         CSize loop = CGRAPH_DEFAULT_LOOP_TIMES);

  template <typename T,
            c_enable_if_t<std::is_base_of<GElement, T>::value, int> = 0>
  CStatus registerGElement(GElementPtr *elementRef,
                           const GElementPtrSet &dependElements =
                               std::initializer_list<GElementPtr>(),
                           const std::string &name = CGRAPH_EMPTY,
                           CSize loop = CGRAPH_DEFAULT_LOOP_TIMES);

  template <typename GFunction>
  CStatus registerGElement(GFunctionPtr *functionRef,
                           const GElementPtrSet &dependElements =
                               std::initializer_list<GElementPtr>(),
                           const std::string &name = CGRAPH_EMPTY,
                           CSize loop = CGRAPH_DEFAULT_LOOP_TIMES);

  template <typename TNode, typename... Args,
            c_enable_if_t<std::is_base_of<GTemplateNode<Args...>, TNode>::value,
                          int> = 0>
  CStatus registerGElement(GTemplateNodePtr<Args...> *elementRef,
                           const GElementPtrSet &dependElements =
                               std::initializer_list<GElementPtr>(),
                           Args... args);

  //   template <typename TNode, typename... Args,
  //             c_enable_if_t<std::is_base_of<GTemplateNode<Args...>,
  //             TNode>::value,
  //                           int> = 0>
  //   CStatus registerGElement(GTemplateNodePtr<Args...> *elementRef,
  //                            const GElementPtrSet &dependElements =
  //                                std::initializer_list<GElementPtr>(),
  //                            Args... args);

  // /**
  //  * 添加切面
  //  * @tparam TAspect
  //  * @tparam TParam
  //  * @param elements
  //  * @param param
  //  * @return
  //  */
  // template <
  //     typename TAspect, typename TParam = GAspectDefaultParam,
  //     c_enable_if_t<std::is_base_of<GAspect, TAspect>::value, int> = 0,
  //     c_enable_if_t<std::is_base_of<GAspectParam, TParam>::value, int> = 0>
  // GPipeline *addGAspect(
  //     const GElementPtrSet &elements = std::initializer_list<GElementPtr>(),
  //     TParam *param = nullptr);

  // /**
  //  * 添加守护
  //  * @tparam TDaemon
  //  * @tparam TParam
  //  * @param ms
  //  * @param param
  //  * @return
  //  */
  // template <
  //     typename TDaemon, typename TParam = GDaemonDefaultParam,
  //     c_enable_if_t<std::is_base_of<GDaemon, TDaemon>::value, int> = 0,
  //     c_enable_if_t<std::is_base_of<GDaemonParam, TParam>::value, int> = 0>
  // GPipeline *addGDaemon(CMSec ms, TParam *param = nullptr);

  // /**
  //  * 添加模板类型守护
  //  * @tparam TAspect
  //  * @tparam Args
  //  * @param ms
  //  * @param args
  //  * @return
  //  */
  // template <
  //     typename TDaemon, typename... Args,
  //     c_enable_if_t<std::is_base_of<GTemplateDaemon<Args...>,
  //     TDaemon>::value,
  //                   int> = 0>
  // GPipeline *addGDaemon(CMSec ms, Args... args);

  template <typename TEvent, typename TParam = GEventDefaultParam,
            c_enable_if_t<std::is_base_of<GEvent, TEvent>::value, int> = 0,
            c_enable_if_t<std::is_base_of<GEventParam, TParam>::value, int> = 0>
  GPipeline *addGEvent(const std::string &key, TParam *param = nullptr);

  GPipeline *setGElementRunTtl(CMSec ttl);
  GPipeline *setGEngineType(GEngineType type);
  GPipeline *setUniqueThreadPoolConfig(const UThreadPoolConfig &config);

  CGRAPH_DECLARE_GPARAM_MANAGER_WRAPPER

protected:
  explicit GPipeline();
  ~GPipeline() override;

  CStatus initSchedule();

  /** 不允许外部赋值和构造 */
  CGRAPH_NO_ALLOWED_COPY(GPipeline)

private:
  GElementManager *element_manager_ =
      nullptr; // 节点管理类（管理所有注册过的element信息）
  GParamManagerPtr param_manager_ = nullptr; // 参数管理类
  // GDaemonManagerPtr daemon_manager_ = nullptr; // 守护管理类
  GEventManagerPtr event_manager_ = nullptr; // 事件管理类
  UThreadPool *thread_pool_ = nullptr;       // 线程池类
  GElementPtrSet element_repository_; // 标记创建的所有节点，最终释放使用

  friend class GPipelineFactory;
  friend class UAllocator;

  // func add avoid template function
  CStatus AddElementManager(GElementPtr eptr);
};

template <typename T, c_enable_if_t<std::is_base_of<GElement, T>::value, int>>
CStatus GPipeline::registerGElement(GElementPtr *elementRef,
                                    const GElementPtrSet &dependElements,
                                    const std::string &name, CSize loop) {
  CGRAPH_FUNCTION_BEGIN
  CGRAPH_ASSERT_INIT(false)

  if (std::is_base_of<GGroup, T>::value) {
    /**
     * 如果是GGroup类型的信息，则：
     * 1，必须外部创建
     * 2，未被注册到其他的pipeline中
     */
    if ((*elementRef) != nullptr && (*elementRef)->param_manager_ != nullptr) {
      CGRAPH_RETURN_ERROR_STATUS("group register duplicate")
    }
  } else if (std::is_base_of<GNode, T>::value) {
    //  std::is_base_of<GAdapter, T>::value) {
    /**
     * 如果不是group信息的话，且属于element（包含node和adapter）
     * 则直接内部创建该信息
     */
    (*elementRef) = new (std::nothrow) T();
  }

  CGRAPH_ASSERT_NOT_NULL(*elementRef)
  status = (*elementRef)
               ->setElementInfo(dependElements, name, loop,
                                this->param_manager_, this->event_manager_);
  CGRAPH_FUNCTION_CHECK_STATUS

  //   status = element_manager_->add(dynamic_cast<GElementPtr>(*elementRef));
  status = AddElementManager(dynamic_cast<GElementPtr>(*elementRef));
  CGRAPH_FUNCTION_CHECK_STATUS
  element_repository_.insert(*elementRef);
  CGRAPH_FUNCTION_END
}

template <typename GFunction>
CStatus GPipeline::registerGElement(GFunctionPtr *functionRef,
                                    const GElementPtrSet &dependElements,
                                    const std::string &name, CSize loop) {
  // 通过模板特化的方式，简化 GFunction 的注册方式
  return this->registerGElement<GFunction>((GElementPtr *)(functionRef),
                                           dependElements, name, loop);
}

template <
    typename TNode, typename... Args,
    c_enable_if_t<std::is_base_of<GTemplateNode<Args...>, TNode>::value, int>>
CStatus GPipeline::registerGElement(GTemplateNodePtr<Args...> *elementRef,
                                    const GElementPtrSet &dependElements,
                                    Args... args) {
  CGRAPH_FUNCTION_BEGIN
  CGRAPH_ASSERT_INIT(false)

  // 构建模板node信息
  (*elementRef) = new (std::nothrow) TNode(std::forward<Args &&>(args)...);
  CGRAPH_ASSERT_NOT_NULL(*elementRef)
  // 以下 name，loop 信息，可以由外部设置
  status = (*elementRef)
               ->setElementInfo(dependElements, CGRAPH_EMPTY,
                                CGRAPH_DEFAULT_LOOP_TIMES, this->param_manager_,
                                this->event_manager_);
  CGRAPH_FUNCTION_CHECK_STATUS

  //   status = element_manager_->add(dynamic_cast<GElementPtr>(*elementRef));
  status = AddElementManager(dynamic_cast<GElementPtr>(*elementRef));
  CGRAPH_FUNCTION_CHECK_STATUS
  element_repository_.insert(*elementRef);
  CGRAPH_FUNCTION_END
}

template <typename T, c_enable_if_t<std::is_base_of<GNode, T>::value, int>>
GNodePtr GPipeline::createGNode(const GNodeInfo &info) {
  CGRAPH_FUNCTION_BEGIN
  GNodePtr node = CGRAPH_SAFE_MALLOC_COBJECT(T) status =
      node->setElementInfo(info.dependence_, info.name_, info.loop_,
                           this->param_manager_, this->event_manager_);
  if (!status.isOK()) {
    CGRAPH_DELETE_PTR(node);
    return nullptr;
  }
  element_repository_.insert(node);
  return node;
}

template <typename T, c_enable_if_t<std::is_base_of<GGroup, T>::value, int>>
GGroupPtr GPipeline::createGGroup(const GElementPtrArr &elements,
                                  const GElementPtrSet &dependElements,
                                  const std::string &name, CSize loop) {
  CGRAPH_FUNCTION_BEGIN

  // 如果不是所有的都非空，则创建失败
  if (std::any_of(elements.begin(), elements.end(),
                  [](GElementPtr element) { return (nullptr == element); })) {
    return nullptr;
  }

  if (std::any_of(dependElements.begin(), dependElements.end(),
                  [](GElementPtr element) { return (nullptr == element); })) {
    return nullptr;
  }

  GGroupPtr group =
      CGRAPH_SAFE_MALLOC_COBJECT(T) for (GElementPtr element : elements) {
    group->addElement(element);
  }

  status = group->setElementInfo(
      dependElements, name, loop, nullptr,
      nullptr); // 注册group信息的时候，不能注册paramManager信息
  if (unlikely(!status.isOK())) {
    // CGRAPH_DELETE_PTR(group)
    delete group;
    return nullptr;
  }

  this->element_repository_.insert(group);
  return group;
}

// template <typename TAspect, typename TParam,
//           c_enable_if_t<std::is_base_of<GAspect, TAspect>::value, int>,
//           c_enable_if_t<std::is_base_of<GAspectParam, TParam>::value, int>>
// GPipelinePtr GPipeline::addGAspect(const GElementPtrSet &elements,
//                                    TParam *param) {
//   CGRAPH_ASSERT_INIT_RETURN_NULL(false)

//   const GElementPtrSet &curElements =
//       elements.empty() ? element_repository_ : elements;
//   for (GElementPtr element : curElements) {
//     // 如果传入的为空，或者不是当前pipeline中的element，则不处理
//     if (nullptr == element ||
//         (element_repository_.find(element) == element_repository_.end())) {
//       continue;
//     }

//     element->addGAspect<TAspect, TParam>(param);
//   }

//   return this;
// }

// template <typename TDaemon, typename TParam,
//           c_enable_if_t<std::is_base_of<GDaemon, TDaemon>::value, int>,
//           c_enable_if_t<std::is_base_of<GDaemonParam, TParam>::value, int>>
// GPipeline *GPipeline::addGDaemon(CMSec ms, TParam *param) {
//   CGRAPH_FUNCTION_BEGIN
//   CGRAPH_ASSERT_INIT_RETURN_NULL(false)
//   CGRAPH_ASSERT_NOT_NULL_RETURN_NULL(param_manager_)
//   CGRAPH_ASSERT_NOT_NULL_RETURN_NULL(daemon_manager_)

//   GDaemonPtr daemon = CGRAPH_SAFE_MALLOC_COBJECT(TDaemon)
//                           daemon->setDParam<TParam>(param)
//                               ->setInterval(ms);
//   daemon->setGParamManager(this->param_manager_);
//   status = daemon_manager_->add(daemon);

//   CGRAPH_CHECK_STATUS_RETURN_THIS_OR_NULL
// }

// template <typename TDaemon, typename... Args,
//           c_enable_if_t<
//               std::is_base_of<GTemplateDaemon<Args...>, TDaemon>::value,
//               int>>
// GPipeline *GPipeline::addGDaemon(CMSec ms, Args... args) {
//   CGRAPH_FUNCTION_BEGIN
//   CGRAPH_ASSERT_INIT_RETURN_NULL(false)
//   CGRAPH_ASSERT_NOT_NULL_RETURN_NULL(param_manager_)
//   CGRAPH_ASSERT_NOT_NULL_RETURN_NULL(daemon_manager_)
//   auto daemon = UAllocator::safeMallocTemplateCObject<TDaemon>(
//       std::forward<Args>(args)...);
//   daemon->setInterval(ms);
//   daemon->setGParamManager(this->param_manager_);
//   status = daemon_manager_->add(daemon);

//   CGRAPH_CHECK_STATUS_RETURN_THIS_OR_NULL
// }

template <typename TEvent, typename TParam,
          c_enable_if_t<std::is_base_of<GEvent, TEvent>::value, int>,
          c_enable_if_t<std::is_base_of<GEventParam, TParam>::value, int>>
GPipeline *GPipeline::addGEvent(const std::string &key, TParam *param) {
  CGRAPH_FUNCTION_BEGIN
  CGRAPH_ASSERT_INIT_RETURN_NULL(false)
  CGRAPH_ASSERT_NOT_NULL_RETURN_NULL(event_manager_)
  CGRAPH_ASSERT_NOT_NULL_RETURN_NULL(param_manager_)

  event_manager_->param_manager_ = this->param_manager_;
  status = event_manager_->createWithParam<TEvent, TParam>(key, param);
  CGRAPH_CHECK_STATUS_RETURN_THIS_OR_NULL
}

using GPipelinePtr = GPipeline *;
using GPipelinePtrList = std::list<GPipelinePtr>;

class GPipelineFactory : public GPipelineObject {
public:
  static GPipelinePtr create();
  static CStatus remove(GPipelinePtr pipeline);
  static CStatus clear();

private:
  static GPipelinePtrList s_pipeline_list_; // 记录所有的
  static std::mutex s_lock_;
};

} // namespace burn